﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RWLibrary.Logic.Queries
{
    using Graph;
    public class NecessaryGoalQuery : GoalQuery
    {
        public NecessaryGoalQuery(Graph graph) : base(graph)
        {
        }

        public override bool Excecute()
        {
            Dictionary<Node, int> fullHistory= new Dictionary<Node, int>();
            Dictionary<Node, int> actualPositions = Graph.Nodes.Where(n => n.IsInitial).ToDictionary(n => n, n => 0);

            while(actualPositions.Count>0)
            {
                Dictionary<Node, int> newPositions = new Dictionary<Node, int>();
                foreach (var actualPosition in actualPositions)
                {
                    if(!Goal.Test(actualPosition.Key.State))
                    {
                        foreach (var edge in actualPosition.Key.Connections)
                        {
                            if(edge.Key.Cost + actualPosition.Value > Cost)
                                return false;
                            if (fullHistory.ContainsKey(edge.Value) && edge.Key.Cost + actualPosition.Value > fullHistory[edge.Value])
                                return false;
                            if (fullHistory.ContainsKey(edge.Value) && edge.Key.Cost + actualPosition.Value == fullHistory[edge.Value])
                                continue;
                            fullHistory[edge.Value] = edge.Key.Cost + actualPosition.Value;
                            if(newPositions.ContainsKey(edge.Value))
                            {
                                if (newPositions[edge.Value] < edge.Key.Cost + actualPosition.Value)
                                    newPositions[edge.Value] = edge.Key.Cost + actualPosition.Value;
                            }
                            else
                            {
                                    newPositions.Add(edge.Value,edge.Key.Cost + actualPosition.Value);
                            }
                        }
                    }
                }
                actualPositions = newPositions;

            }
            return true;

        }
    }
}
